/**
*  \file mcu.c
*
*  \brief
*
*  \author Michael J. Hohmann  <michael.hohmann@linde-mh.de>
*
*
*/

/*===============================================[ private includes  ]================================================*/
#include "mcu.h"
#include "../assertor/assertor.h"
#include "../sched/sched.h"
#include "../input/input.h"
#include "../app/app.h"
/*===============================================[ private defines   ]================================================*/


/*===============================================[ private datatypes ]================================================*/

struct mcu_port
{
	U16 in;
	U16 out;
};


/** Private variables */
struct mcu_private
{
   U16 adc[mcu_adc_max_chn];
   //U16 dac[16];
   U16 pwm[16];
   //BO  out[64];
   //BO  in[64];

   BO  outputs_changed;
   struct tasklet task_10ms;                                     /**< tasklet running on 10ms loop of RTS */
   struct mcu_port port[6];

};

/*===============================================[ private variables ]================================================*/
static struct mcu_private mcu;

/*===============================================[ private functions ]================================================*/
static void mcu_10ms_service (struct tasklet *task);

/*===============================================[ inline functions  ]================================================*/

/*===============================================[ public functions  ]================================================*/
RC mcu_initialize( void )
{
   pal_memzero( &mcu, sizeof mcu);
   mcu.outputs_changed=TRUE;

   tasklet_assign( sched_get_slice_10ms(), &mcu.task_10ms,  mcu_10ms_service, NIL );


   return RC_SUCCESS;
}

U16 mcu_get_adc( enum mcu_adc  channel )
{
   return mcu.adc[channel];
}

void mcu_set_adc_sim(U8 channel, S16 value )
{
   if (value < 0 )
   {
      /* ignore value */
   }
   else
   {
      mcu.adc[channel]=(U16) value;
   }
}


U16 mcu_get_pwm_sim(U8 channel )
{
   return mcu.pwm[channel];
}

void mcu_set_pwm(enum mcu_pwm channel, U16 value )
{
   mcu.pwm[channel]=value;
}

void mcu_set_output( enum mcu_output pin, BO value )
{
   if(value)
   {
	   mcu.port[pin>>8].out|=1<<(pin&0xFF);
   }
   else
   {
	   mcu.port[pin>>8].out&=~(1<<(pin&0xFF));
   }
}

BO mcu_get_output_sim( U16 pin )
{
	return !!(mcu.port[pin>>8].out&(~(1<<(pin&0xFF))));
}

U16 mcu_get_port_out_sim( U16 port )
{
	return mcu.port[port].out;
}



BO mcu_update_outputs_sim(void)
{
   BO rv=mcu.outputs_changed;
   mcu.outputs_changed=FALSE;
   return rv;
}

void mcu_set_input_sim( U16 pin, BO value )
{
	ASSERTOR_PRE(FALSE,"not expected to call this anymore");
	//mcu.in[pin]=!!value;
}


void mcu_set_port_sim( U16 port, U16 value )
{
   mcu.port[port].in = value;
}


BO mcu_get_input( enum mcu_input pin )
{
	return !!(mcu.port[pin>>8].in & (1<<(pin&0x00FF)));
}

void mcu_set_main_relay( BO value )
{
   mcu_set_output(3, value );
}


U32 mcu_get_reset_reason(void)
{
    return 0;
}

static void mcu_10ms_service (struct tasklet *task)
{
   UNREFERENCED( task );

}


void mcu_delay_ms( U32 delay_ms)
{
	UNREFERENCED( delay_ms );
}

BO mcu_i2c_transmit(enum i2cgi_cmd cmd, U8 control, void* data, pal_size_t len )
{
   return TRUE;
}


U32 mcu_high_resolution_counter(void)
{
   return 0;
}

U32 mcu_get_build_time_app(void)
{
   return 0;
}

U32 mcu_get_build_time_bb(void)
{
   return 0;
}

F32 mcu_get_motor_speed(void)
{
   return input_data.mL_nSen_Can;
}

/*===============================================[ private functions ]================================================*/


/***********************************************************************************************************************
*                             Copyright 2018 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
